package com.example.bledemo.tool;

import android.util.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by Peter_Z.
 * <p>
 * Date: 2024/10/10 0010
 */
public class Algorithm {
    public static ConcurrentHashMap<String, MapModel> dl_map = new ConcurrentHashMap<>();
    public static String TAG = "Algorithm";


    // 这是一个静态方法，用于获取指定目录下所有以 .bin 结尾的文件
    public static File[] getBinFiles(File directory) {
        Log.d(TAG,"file... directory.exists()"+directory.exists());
        Log.d(TAG,"file... directory.isDirectory()"+directory.isDirectory());
        if (!directory.exists() || !directory.isDirectory()) {
            Log.d(TAG,"file... 目录不存在或者不是目录");
            return new File[0]; // 如果目录不存在或不是目录，返回空数组
        }
//        Log.d(TAG,"file...directory"+directory.listFiles().length);
        // 使用 FilenameFilter 接口来过滤文件名
        FilenameFilter filter = new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".bin");
            }
        };

        // 列出所有符合过滤条件的文件
        return directory.listFiles(filter);
    }
    // 初始化地图数据
    public static void initMap(){
        Log.d(TAG,"加载地图中...");

//        String directoryPath = "/sdcard/test/"; // 示例路径
        String directoryPath = "/storage/emulated/0/Android/data/com.example.rtls_sensor_example_android_java/files/"; // 示例路径

        File[] files = getBinFiles(new File(directoryPath));

        if (files == null || files.length <= 0) {
            Log.d(TAG,"地图文件数据为空...");
            return;
        }

        int index = 0;
        try {
            for (File file : files) {
                String map_id = file.getName().substring(0, file.getName().lastIndexOf('.'));
                MapModel mapModel = loadMapDataFromFile(file.getAbsolutePath());
                dl_map.putIfAbsent(map_id, mapModel);
                Log.d(TAG, "222MAPid:" + map_id);
                index++;
            }
        }catch (Exception e){
            Log.d(TAG,"加载地图失败...");
        }
        Log.d(TAG,"地图加载完成！共加载[" + index + "]个地图");
    }
    public static void initMap(File file){
        Log.d(TAG,"222加载地图中...");

        try {
            Log.d(TAG, "222getName:" + file.getName());
            Log.d(TAG, "222substring:" + file.getName().substring(0, file.getName().lastIndexOf('.')));
            String map_id = file.getName().substring(0, file.getName().lastIndexOf('.'));
            MapModel mapModel = loadMapDataFromFile(file.getAbsolutePath());
            dl_map.putIfAbsent(map_id, mapModel);
            Log.d(TAG, "222MAPid:" + map_id);
        }catch (Exception e){
            Log.d(TAG,"222加载地图失败..."+e);
        }
        Log.d(TAG,"222地图加载完成！共加载[" + "1" + "]个地图");
    }
    public static int getMapWz(int X, int Y, String mapId) {
        MapModel mapModel = dl_map.get(mapId);
        int[][] map = mapModel.getMap();
        int gridSize = mapModel.getGridSize();
        boolean isok = map[Y / gridSize][X / gridSize] == 1;
        return isok ? 1 : 0; // Assuming return 1 for true and 0 for false
    }

//    public static boolean isClean(Point start, String mapId) {
//        MapModel mapModel = dl_map.get(mapId);
//        int[][] map = mapModel.getMap();
//        int gridSize = mapModel.getGridSize();
//        Point startGrid = new Point(start.y / gridSize, start.x / gridSize);
//        return map[startGrid.x][startGrid.y] == 1;
//    }

    public static List<Point> startPlan(Point start, Point end, String mapId) {
        MapModel mapModel = dl_map.get(mapId);
        int[][] map = mapModel.getMap();
        int gridSize = mapModel.getGridSize();
        Log.d(TAG,"gridSize..."+gridSize);
        List<Point> path = new ArrayList<>();

        try {
            Point startGrid = new Point(start.Y / gridSize, start.X / gridSize);
            Point endGrid = new Point(end.Y / gridSize, end.X / gridSize);
//            Log.d(TAG,"点位状态...");
//            Log.d(TAG,"开始："+startGrid);
//            Log.d(TAG,"结束："+endGrid);
            List<Point> result = aStarSearch(map, startGrid, endGrid);
            if (result != null) {
                for (Point p : result) {
                    p.X = p.X * gridSize;
                    p.Y = p.Y * gridSize;
                }
                path = result;
            }
        } catch (Exception ex) {
            Log.e(TAG,"计算路径出错: " + ex.getMessage());
        }
        return path;
    }

    // A* Search Algorithm
    public static List<Point> aStarSearch(int[][] map, Point start, Point end) {
        int width = map.length;
        int height = map[0].length;

        // 创建开放列表和关闭列表
        PriorityQueue<Node> openList = new PriorityQueue<Node>();
        HashSet<Point> closedList = new HashSet<Point>();

        // 初始化起点和终点的节点
        Node startNode = new Node(start, 0, Heuristic(start, end), null);
        Node endNode = new Node(end);

        // 将起点添加到开放列表
        openList.enqueue(startNode);

        while (openList.getCount() > 0) {
            Node currentNode = openList.dequeue();
            closedList.add(currentNode.getPosition());

            if (currentNode.equals(endNode)) {
                return generatePath(currentNode);
            }

            List<Node> neighbors = getNeighbors(map, currentNode.getPosition(), width, height);

            for (Node neighbor : neighbors) {
                if (closedList.contains(neighbor.getPosition())) {
                    continue;
                }

                int g = currentNode.G + 1;

                if (!openList.contains(neighbor) || g < neighbor.G) {
                    neighbor.G = g;
                    neighbor.H = Heuristic(neighbor.getPosition(), end);
                    neighbor.parent = currentNode;

                    if (!openList.contains(neighbor)) {
                        openList.enqueue(neighbor);
                    }
                }
            }
        }

        return null;
    }

    public static int Heuristic(Point current, Point end) {
        return Math.abs(current.X - end.X) + Math.abs(current.Y - end.Y);
    }

    public static List<Node> getNeighbors(int[][] map, Point position, int width, int height) {
        List<Node> neighbors = new ArrayList<>();

        int[][] directions = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};

        for (int[] direction : directions) {
            int x = position.X + direction[0];
            int y = position.Y + direction[1];

            if (x >= 0 && x < width && y >= 0 && y < height && map[x][y] == 0) {
                neighbors.add(new Node(new Point(x, y)));
            }
        }

        return neighbors;
    }

    public static List<Point> generatePath(Node endNode) {
        List<Point> path = new ArrayList<>();
        Node currentNode = endNode;

        while (currentNode != null) {
            path.add(currentNode.getPosition());
            currentNode = currentNode.parent;
        }

        Collections.reverse(path);
        return path;
    }

    // 加载地图文件
    public static MapModel loadMapDataFromFile(String fileName) throws IOException {
        MapModel model = new MapModel();
        int[][] mapData;

        try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
            int rows = Integer.parseInt(reader.readLine());
            int cols = Integer.parseInt(reader.readLine());
            model.setGridSize(Integer.parseInt(reader.readLine()));
            mapData = new int[rows][cols];

            for (int i = 0; i < rows; i++) {
                String[] values = reader.readLine().split(" ");

                for (int j = 0; j < cols; j++) {
                    mapData[i][j] = Integer.parseInt(values[j]);
                }
            }
        }

        model.setMap(mapData);
        return model;
    }

}